package com.hibernate.annotation.entity;

import java.io.Serializable;

import javax.persistence.*;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

/**
 * stock: 与stockDetail是一对一的关系
 * 
 * @author Administrator
 *
 */
@SuppressWarnings("all")
// 类中添加的注解,hibernate的annotation是基于jpa的
/*
  @Entity:映射实体类标注，使用默认的orm规则，即class名即数据库表中表名，class字段名即表中的字段名
  */
@Entity
/*
  @Table:实体类对应的数据库表的信息
  name:可选，映射表名称，默认表名和实体名称一致，只有在不一致的情况下需要指定表名
  @UniqueConstraints 定义表的唯一约束,如果是联合约束：@UniqueConstraint(columnNames={"字段名1", "字段名2"}
          如果使用的是uuid方式，则要注意：id是String类型的
  */
@Table(name = "stock", uniqueConstraints = {
		@UniqueConstraint(columnNames = "stock_code"),
		@UniqueConstraint(columnNames = "stock_name") })
public class Stock implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/*
    @Id 表示这个主键
    @GeneratedValue 表示ID的生成策略，默认是native,JPA通用策略生成器
      TABLE：使用一个特定的数据库表格来保存主键。
        使用一个特定的数据库表格来保存主键,持久化引擎通过关系数据库的一张特定的表格来生成主键,这种策略的好处就是不依赖于外部环境和数据库的具体实现,
        在不同数据库间可以很容易的进行移植,但由于其不能充分利用数据库的特性,所以不会优先使用。该策略一般与另外一个注解一起使用@TableGenerator,
        @TableGenerator注解指定了生成主键的表(可以在实体类上指定也可以在主键字段或属性上指定),然后JPA将会根据注解内容自动生成一张表作为序列表
        (或使用现有的序列表)。如果不指定序列表,则会生成一张默认的序列表,表中的列名也是自动生成,数据库上会生成一张名为sequence的表(SEQ_NAME,SEQ_COUNT)。
        序列表一般只包含两个字段:第一个字段是该生成策略的名称,第二个字段是该关系表的最大序号,它会随着数据的插入逐渐累加。
          	@GeneratedValue(strategy=GenerationType.TABLE,generator="table_gen")
            @TableGenerator(
                  name = "table_gen",          //name属性表示该表主键生成策略的名称，它被引用在@GeneratedValue中设置的“generator”值中。
                  table="fendo_generator",     //table属性表示表生成策略所持久化的表名
                  valueColumnName="seq_id",    //该主键当前所生成的值，它的值将会随着每次创建累加
                  pkColumnName="seq_name",     //指定主键的名字
                  pkColumnValue="fendos",      //指定下次插入主键时使用默认的值
                  initialValue = 1,            //初始化值
                  allocationSize=1             //累加值
            )

            CREATE TABLE `fendo_generator` (
              `seq_id` int(11) NOT NULL,
              `seq_name` varchar(255) NOT NULL,
              PRIMARY KEY (`seq_id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


      SEQUENCE：根据底层数据库的序列来生成主键，条件是数据库支持序列。该策略一般与另外一个注解一起使用@SequenceGenerator,
                @SequenceGenerator注解指定了生成主键的序列.然后JPA会根据注解内容创建一个序列(或使用一个现有的序列)。如果
                不指定序列,则会自动生成一个序列SEQ_GEN_SEQUENCE

                属性说明:
                name属性: 表示该表主键生成策略的名称，它被引用在@GeneratedValue中设置的“generator”值中。
                sequenceName属性: 表示生成策略用到的数据库序列名称。
                initialValue属性: 表示主键初识值，默认为0。
                allocationSize属性: 表示每次主键值增加的大小，例如设置成1，则表示每次创建新记录后自动加1，默认为50。

                @GeneratedValue(strategy = GenerationType.SEQUENCE,generator="fendo_seq")
                @SequenceGenerator(name="fendo_seq", sequenceName="seq_name")

      IDENTITY：主键由数据库自动生成（主要是自动增长型）
                此种主键生成策略就是通常所说的主键自增长,数据库在插入数据时,会自动给主键赋值,比如MySQL可以在创建表时声明
                "auto_increment" 来指定主键自增长。该策略在大部分数据库中都提供了支持(指定方法或关键字可能不同),但还是
                有少数数据库不支持,所以可移植性略差。使用自增长主键生成策略是只需要声明strategy = GenerationType.IDENTITY
                即可

      AUTO：主键由程序控制。
                把主键生成策略交给持久化引擎(persistence engine),持久化引擎会根据数据库在以上三种主键生成策略中选择其中一种。
                此种主键生成策略比较常用,由于JPA默认的生成策略就是GenerationType.AUTO,所以使用此种策略时.可以显式的指定
                @GeneratedValue(strategy = GenerationType.AUTO)也可以直接@GeneratedValue。




    @Column字段映射:
      name: 字段名
      unique: 列的值是否是唯一
      nullable: 列的值是否允许为 null。默认为 true
      insertable: 列是否包含在 INSERT 语句中，默认为 true
      updatable: 列是否包含在 UPDATE 语句中，默认为 true
      columnDefinition: 生成列的 DDL 时使用的 SQL 片段。
      table: 当前列所属的表的名称
      length: 列的长度，仅对字符串类型的列生效。默认为255
      precision: 列的精度，仅对十进制数值有效，表示有效数值的总位数。默认为0
      scale: 列的精度，仅对十进制数值有效，表示小数位的总位数。默认为0
	  */
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "stock_id", unique = true, nullable = false)
	private Integer stockId;

	/*
	  映射一对多：OneToOne
      fetch属性默认值是FetchType.EAGER(立即加载)。optional=false时,FetchType.LAZY才能起作用；
      targetEntity属性:Class类型的属性。定义关系类的类型，默认是该成员属性对应的类类型，所以通常不需要提供定义；
      cascade属性：CascadeType[]类型。该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作，而且这种关系是递归调用的。cascade的值只能从CascadeType.PERSIST（级联新建）、CascadeType.REMOVE（级联删除）、CascadeType.REFRESH（级联刷新）、CascadeType.MERGE（级联更新）中选择一个或多个。还有一个选择是使用CascadeType.ALL，表示选择全部四项
      mappedBy: 在the owned side(被拥有方的)，他指向the owning side(拥有方)。

    级联操作: Cascade
      CascadeType[],配置同OneToOne的cascade属性
	  */
	@OneToOne(mappedBy = "stock",fetch = FetchType.LAZY)
	@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE })
	private StockDetail stockDetail;

	@Column(name = "stock_code", length = 10, nullable = false)
	private String stockCode;

	@Column(name = "stock_name", length = 20, nullable = false)
	private String stockName;

	public Stock() {
	}

	public Stock(Integer stockId, StockDetail stockDetail, String stockCode,
			String stockName) {
		super();
		this.stockId = stockId;
		this.stockDetail = stockDetail;
		this.stockCode = stockCode;
		this.stockName = stockName;
	}

	public Integer getStockId() {
		return stockId;
	}

	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}

	public String getStockCode() {
		return stockCode;
	}

	public void setStockCode(String stockCode) {
		this.stockCode = stockCode;
	}

	public String getStockName() {
		return stockName;
	}

	public void setStockName(String stockName) {
		this.stockName = stockName;
	}

	public StockDetail getStockDetail() {
		return stockDetail;
	}

	public void setStockDetail(StockDetail stockDetail) {
		this.stockDetail = stockDetail;
	}

}
